package com.fubowen.lepton.ui.search

import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.fubowen.lepton.R
import com.fubowen.lepton.bean.BookmarkBean
import com.fubowen.lepton.bean.Setting
import com.fubowen.lepton.bean.VisitedBean
import com.fubowen.lepton.conf.AnnotationConfig
import com.fubowen.lepton.conf.Command
import com.fubowen.lepton.conf.SiteConfigViewModel
import com.fubowen.lepton.databinding.FragmentSearchListItemDetailBinding
import com.fubowen.lepton.extension.documentText
import com.fubowen.lepton.extension.toUrl
import com.fubowen.lepton.helper.DBHelper
import com.fubowen.lepton.helper.ImageHelper.bitmapToFavicon
import com.fubowen.lepton.helper.ViewHelper.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


class SearchListItemDetailFragment : Fragment() {


    private lateinit var binding: FragmentSearchListItemDetailBinding
    private lateinit var webView: WebView
    private lateinit var callback: OnBackPressedCallback
    private val args: SearchListItemDetailFragmentArgs by navArgs()
    private var isErrorPage = false
    private val viewModel: SiteConfigViewModel by activityViewModels()
    private var isInterceptJump = false
    private var content = ""

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchListItemDetailBinding.inflate(inflater, container, false)
        webView = binding.searchWebView
        goBack()
        initWebView()
        initToolMenu()
        initToolMenuListener()
        binding.tetete.setOnClickListener {
            if (!content.isNullOrBlank() && content != "null") {
//                val action =
//                    SearchListItemDetailFragmentDirections.actionSearchListItemDetailFragmentToReaderFragment(
//                        content = content
//                    )
//                findNavController().navigate(action)
            }
        }
        return binding.root
    }
    
    // region goBack，initWebView，webChromeClient，webViewClient

    private fun setOrPut(key: String, value: Any) {
        CoroutineScope(Dispatchers.IO).launch {
            DBHelper.db.settingDao().setOrPut(
                Setting(
                    key = key,
                    value = value.toString(),
                    nameSpace = "web-view"
                )
            )
        }
    }

    private fun goBack() {
        callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (webView.canGoBack()) {
                    webView.goBack()
                } else {
                    isEnabled = false
                    findNavController().navigateUp()
                }
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
    }

    private fun initWebView() {
        webView.settings.javaScriptEnabled = true
        webView.settings.useWideViewPort = true
        webView.settings.loadWithOverviewMode = true
        webView.settings.javaScriptCanOpenWindowsAutomatically = false
        webView.settings.loadsImagesAutomatically = true
        webView.settings.builtInZoomControls = true
        webView.settings.setSupportZoom(true)
        webView.settings.displayZoomControls = false
        webView.webViewClient = webViewClient
        webView.webChromeClient = webChromeClient
        webView.loadUrl(args.url)
    }

    private val webChromeClient = object : WebChromeClient() {
        override fun onProgressChanged(view: WebView?, newProgress: Int) {
            binding.searchWebViewProgress.progress = newProgress
            if (newProgress == 100) {
                binding.searchWebViewProgress.visibility = View.GONE
            } else {
                binding.searchWebViewProgress.visibility = View.VISIBLE
            }
        }
    }

    private val webViewClient = object : WebViewClient() {

        override fun shouldOverrideUrlLoading(
            view: WebView?,
            request: WebResourceRequest?
        ): Boolean {
            if (isIntercept(view, request)) {
                return true
            }
            appendVisited(request?.url?.toString(), view?.favicon, view?.title)
            return false
        }

        override fun shouldInterceptRequest(
            view: WebView?,
            request: WebResourceRequest?
        ): WebResourceResponse? {
//            viewModel.imageState.value.let { state ->
//                if (state == ImageStateEnum.ZERO_IMAGE) {
//                    val allow = listOf(".png", ".jpeg", ".gif")
//                    val url = request?.url?.toString() ?: ""
//                    val hasImage = allow.any { suffix -> url.endsWith(suffix) }
//                    if (hasImage) {
//                        val input = ImageHelper.createEmptyImage()
//                        return WebResourceResponse("image/png", "utf-8", input)
//                    }
//                }
//            }
            return super.shouldInterceptRequest(view, request)
        }

        override fun onReceivedError(
            view: WebView?,
            errorCode: Int,
            description: String?,
            failingUrl: String?
        ) {
            isErrorPage = true
        }

        override fun onPageFinished(
            view: WebView?,
            url: String?
        ) {
            if (!isErrorPage) {
                appendVisited(url, view?.favicon, view?.title)
            }
            webView.documentText { text ->
                content = text
            }
            isErrorPage = false
        }
    }

    //endregion

    private fun initToolMenu() {
        CoroutineScope(Dispatchers.IO).launch {
            DBHelper.db.settingDao().nameSpaceFlow("web-view").collect {
                webView.apply {
                    post {
                        val js = it.firstOrNull { it.key == "javaScriptEnabled" }
                        settings.javaScriptEnabled = js?.value?.toBoolean() ?: true
                        viewModel.receiveCommand(
                            Command(
                                id = R.id.tool_script_container,
                                isChecked = !settings.javaScriptEnabled
                            )
                        )

                        val img = it.firstOrNull { it.key == "blockNetworkImage" }
                        settings.blockNetworkImage = img?.value?.toBoolean() ?: false
                        viewModel.receiveCommand(
                            Command(
                                id = R.id.tool_images_container,
                                isChecked = settings.blockNetworkImage
                            )
                        )

                        val jump = it.firstOrNull { it.key == "isInterceptJump" }
                        isInterceptJump = jump?.value?.toBoolean() ?: false
                        viewModel.receiveCommand(
                            Command(
                                id = R.id.tool_jumpTo_container,
                                isChecked = isInterceptJump
                            )
                        )

                    }
                }
            }
        }
    }

    private fun initToolMenuListener() {
        viewModel.command.observe(viewLifecycleOwner) {
            when (it.id) {
                R.id.tool_reader_container -> {

                }

                R.id.tool_images_container -> {
                    val enable = webView.settings.blockNetworkImage
                    webView.settings.blockNetworkImage = !enable
                    setOrPut("blockNetworkImage", !enable)
                    webView.reload()
                }

                R.id.tool_script_container -> {
                    val enable = webView.settings.javaScriptEnabled
                    webView.settings.javaScriptEnabled = !enable
                    setOrPut("javaScriptEnabled", !enable)
                    webView.reload()
                }

                R.id.tool_jumpTo_container -> {
                    isInterceptJump = !isInterceptJump
                    setOrPut("isInterceptJump", isInterceptJump)
                }
            }
        }
    }

    private fun appendBookmark() {
        CoroutineScope(Dispatchers.Main).launch {
            val path = requireContext().bitmapToFavicon(webView.favicon, webView.url)
            val bookmark = BookmarkBean(
                title = webView.title,
                url = webView.url,
                host = webView.url.toUrl()?.host,
                icon = path,
                iconSource = AnnotationConfig.ICON_SOURCE_URL,
            )
            DBHelper.db.bookmarkDao().setOrReplace(bookmark)
        }
    }

    private fun appendVisited(url: String?, favicon: Bitmap?, title: String?) {
        val path = requireContext().bitmapToFavicon(favicon, url)
        val bean = VisitedBean(
            title = title,
            url = url,
            icon = path,
            iconSource = AnnotationConfig.ICON_SOURCE_URL,
            host = url?.toUrl()?.host
        )
        CoroutineScope(Dispatchers.IO).launch {
            DBHelper.db.visitedDao().setOrReplace(bean)
        }
    }

    private fun isIntercept(view: WebView?, request: WebResourceRequest?): Boolean {
        if (isInterceptJump) {
            val source = Uri.parse(view?.url)
            val target = request?.url
            if (!source.host.equals(target?.host)) {
                webView.toast("访问已拦截", 3000)
                return true
            }
        }
        return false
    }

    private fun download(view: WebView?, request: WebResourceRequest?): Boolean {
        //                val downloadManager =
//                    context!!.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
//                val request11 = DownloadManager.Request(request?.url)
//                request11.setTitle("123123")
//                request11.setDescription("fffffff")
//                var id = downloadManager.enqueue(request11);
//                // 查询下载任务的状态和进度
//                // 查询下载任务的状态和进度
//                val query = DownloadManager.Query()
//                query.setFilterById(id)
//
//                val cursor = downloadManager.query(query)
//                if (cursor.moveToFirst()) {
//                    val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
//                    val downloadedBytes =
//                        cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
//                    val totalBytes =
//                        cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
//                    if (status == DownloadManager.STATUS_RUNNING && totalBytes != -1) {
//                        val progress = (downloadedBytes * 100L / totalBytes).toInt()
//                        val builder: NotificationCompat.Builder = Builder(context)
//                            .setSmallIcon(R.drawable.ic_download)
//                            .setContentTitle("Downloading File")
//                            .setContentText("Download progress: $progress%")
//                            .setProgress(100, progress, false)
//                        val notificationManager =
//                            requireContext(). getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
//                        notificationManager!!.notify(builder.id, builder.build())
//                    }
//                }
//                
        return false
    }
}